from typing import Any

from aiogram import Bot, types
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import Back, Button, Cancel, Group
from pydantic import ValidationError
from sqlalchemy.exc import DBAPIError

from app.bot.dialog.dialog_states import BuyProxySubscriptionSG
from app.bot.dialog.getters.orders import subscription_summary_getter
from app.bot.dialog.widgets import LocaleText
from app.bot.schemas.order import OrderModel
from app.bot.services.broadcaster import broadcast
from app.bot.services.date_time import get_date_time
from app.bot.services.helpers import get_expiring_on
from app.bot.services.locale import Locale
from app.bot.services.loggers import logger
from app.config import Settings
from app.database.services.categories import get_category_by_name
from app.database.services.orders.common import create_order
from app.database.services.stats import update_stats
from app.database.services.users import get_user


async def set_subscription_period(
    call: types.CallbackQuery, widget: Any, manager: DialogManager
):

    manager.dialog_data["subscription_period"] = widget.widget_id

    await manager.switch_to(BuyProxySubscriptionSG.create_order)


async def add_order(message: types.Message, widget: Any, manager: DialogManager):
    db_session = manager.middleware_data.get("db_session")
    locale: Locale = manager.middleware_data.get("locale")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")

    subscription_summ: float = manager.dialog_data.get("subscription_summ")

    user_id: int = message.from_user.id
    user = await get_user(db_session, user_id)

    if user.balance < subscription_summ:
        await message.answer(locale.get("not-enough-balance", balance=user.balance))
        return

    try:
        period: str = manager.dialog_data.get("subscription_period")

        date_now = get_date_time(get_datetime=True)

        expiring_on = await get_expiring_on(date_now, period)

        category = await get_category_by_name(db_session, "Подписка")
        order = OrderModel(
            type="subscription",
            user_id=user_id,
            proxies=[],
            summ=subscription_summ,
            period=period,
            category_id=category.id,
            expiring_on=expiring_on,
        )

        order = await create_order(db_session, **order.dict())

        await update_stats(db_session, subscriptions=1)
        await message.answer(locale.get("order-success"))
        await db_session.commit()
        logger.info(f"Добавлена новая подписка {order.id}")
        await manager.done()

    except (DBAPIError, ValidationError, Exception) as e:
        logger.exception(e)
        await message.answer(locale.get("error-msg"))
        await broadcast(
            bot,
            [config.tg_bot.developer_id],
            f"Ошибка во время создания заказа {str(e)}",
        )


select_plan_window = Window(
    LocaleText("select-subscription-plan"),
    Group(
        Button(LocaleText("one_day"), id="one_day", on_click=set_subscription_period),
        Button(
            LocaleText("two_weeks"), id="two_weeks", on_click=set_subscription_period
        ),
        Button(
            LocaleText("one_month"), id="one_month", on_click=set_subscription_period
        ),
        width=2,
    ),
    Cancel(LocaleText("back-btn")),
    state=BuyProxySubscriptionSG.select_plan,
)


create_order_window = Window(
    LocaleText("order-overview"),
    LocaleText("selected-period", period="{period}"),
    LocaleText("order-summ", order_summ="{subscription_summ}$"),
    Button(
        LocaleText("confirm-btn"),
        id="confirm_order_button",
        on_click=add_order,
    ),
    Back(LocaleText("back-btn")),
    Cancel(LocaleText("cancel-btn")),
    state=BuyProxySubscriptionSG.create_order,
    getter=subscription_summary_getter,
)


buy_subscription_dialog = Dialog(select_plan_window, create_order_window)
